﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ComponentModel;

namespace WingOpenSourceComponentWP
{
    public class BoundProperty<T> : INotifyPropertyChanged
    {
        public BoundProperty()
        {
            _excuteQueueOnPropertyChanged = new List<Action<T>>();
            _excuteComparedQueueOnPropertyChanged = new List<Action<T , T>>();
            
        }
        public BoundProperty(T BoundOb)
        {
            _excuteQueueOnPropertyChanged = new List<Action<T>>();
            _excuteComparedQueueOnPropertyChanged = new List<Action<T , T>>();
            _boundInstance = BoundOb;
        }
        private T _boundInstance;
        public T BoundInstance
        {
            get
            {
                return _boundInstance;
            }
            set
            {
                T oldT = _boundInstance;//ref type or value type?
                T newT = value;
                Excute(oldT , newT);

                _boundInstance = value;
                NotifyPropertyChanged("BoundInstance");
                Excute(value);

            }
        }

        private List<Action<T>> _excuteQueueOnPropertyChanged;
        public List<Action<T>> ExcuteQueueOnPropertyChanged
        {
            get
            {
                return _excuteQueueOnPropertyChanged;
            }
            set
            {
                _excuteQueueOnPropertyChanged = value;
            }
        }

        private List<Action<T , T>> _excuteComparedQueueOnPropertyChanged;
        public List<Action<T , T>> ExcuteComparedQueueOnPropertyChanged
        {
            get
            {
                return _excuteComparedQueueOnPropertyChanged;
            }
            set
            {
                _excuteComparedQueueOnPropertyChanged = value;
            }
        }
        private void Excute(T newT)
        {
            _excuteQueueOnPropertyChanged.ForEach(item => item.Invoke(newT));
        }
        private void Excute(T oldT , T newT)
        {
            _excuteComparedQueueOnPropertyChanged.ForEach(item => item.Invoke(oldT , newT));
        }
        public override string ToString()
        {
            return _boundInstance.ToString();
        }

        public void SetValue(T v)
        {
            this.BoundInstance = v;
        }

        public static void SetBinding(BoundProperty<T> BoundInstance , Action<T> Excute)
        {
            BoundInstance.ExcuteQueueOnPropertyChanged.Add(Excute);
        }

        public static void SetBinding(BoundProperty<T> BoundInstance , Action<T , T> Excute)
        {
            BoundInstance.ExcuteComparedQueueOnPropertyChanged.Add(Excute);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this , new PropertyChangedEventArgs(PropertyName));
            }
        }
    }
}
